home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
newsgrp
/
group98c.txt
/
000153_icon-group-sender _Fri Dec 25 18:21:28 1998.msg
< prev
next >
Wrap
Internet Message Format
|
2000-09-20
|
20KB
Return-Path: <icon-group-sender>
Received: from ursus.CS.Arizona.EDU (ursus.CS.Arizona.EDU [192.12.69.63])
by baskerville.CS.Arizona.EDU (8.9.1a/8.9.1) with SMTP id SAA20391
for <icon-group-addresses@baskerville.CS.Arizona.EDU>; Fri, 25 Dec 1998 18:21:27 -0700 (MST)
Received: by ursus.CS.Arizona.EDU (5.65v4.0/1.1.8.2/08Nov94-0446PM)
id AA01644; Fri, 25 Dec 1998 18:21:26 -0700
Date: Thu, 24 Dec 1998 05:16:02 -0600
Message-Id: <199812241116.FAA01376@segfault.cs.utsa.edu>
From: Clinton Jeffery <jeffery@segfault.cs.utsa.edu>
To: icon-group@optima.CS.Arizona.EDU
Cc: davidr1@express-news.net
Subject: Merry Christmas to all
Reply-To: jeffery@cs.utsa.edu
Errors-To: icon-group-errors@optima.CS.Arizona.EDU
Status: RO
In the spirit of our own Chris Tenaglia, who has contributed more games to
the Icon community than anyone else, especially on holidays, I would like
to present you with a fine version of the classic game of Tetris. It was
written by high school senior David Rice, and will be featured in our
forthcoming book, Programming with Icon. It runs unmodified on UNIX and
Windows Icon, requires graphics facilities, is only a few hundred lines
long, and has a nice feature set. If you enhance it further, David and
I would love to get copies of your improvements. I can personally vouch
that it is highly playable, but if you find any bugs or have any problems
with it, we would like to know about that too. Cheers!
Clint Jeffery, jeffery@cs.utsa.edu
Division of Computer Science, The University of Texas at San Antonio
Research http://www.cs.utsa.edu/research/plss.html
Will Hack For Food!
############################################################################
#
# File: iTetris.icn
#
# Subject: An Icon version of the classic game Tetris
#
# Author: David Rice
#
# Date: December 10, 1998
#
############################################################################
#
# Version: 2.0
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# This program generates random pieces that fall from the top
# of the screen. The object is to position the pieces in a way
# that they complete a horizontal row. Scoring is done by 50
# points for one row, 100 for two, 200 for three, and 400
# points for a tetris, or four rows. Another five points are
# awarded for every piece played. Levels increase every time
# that ten rows are deleted.
#
############################################################################
#
# Requires: Version 9 graphics
#
############################################################################
#
# Links: graphics, random
#
############################################################################
link graphics
link random
$include "keysyms.icn"
global activecells, activecellcolor, nextpiece, nextcolor, L,
colors, score, numrows, level, delaytime, pieceposition,
button_status, game_status
procedure main()
repeat {
game_status := 0
init()
text1 := ["Start", "green", 45, 285]
text2 := ["Pause", "red", 40, 285]
button_status := 0
repeat
if buttons(15, 105, 270, 290, text1, text2) == "done" then break
every cell := !nextpiece do
drawcell(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15,
nextcolor)
every cell := !activecells do
if cell ~=== colors["black"] then
drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
game_status := 1
game_loop()
}
end
procedure init()
randomize()
if /&window then {
&window := open("iTetris","g","size=276,510", "posx=20",
"bg=black")
}
WAttrib("fg=white", "bg=black", "font=sans,bold,15")
EraseArea(0, 0, 276, 510)
DrawString(15,50,"Next Object")
WAttrib("bg=vivid blue", "font=serif,italic,bold,16")
GotoXY(4,16)
WWrites(" ITETRIS 2.0 ")
WAttrib("fg=dark weak greenish cyan", "linewidth=1", "font=sans,bold,16")
DrawRectangle(15, 270, 90, 20, 15, 300, 90, 20,
15, 330, 90, 20, 15, 360, 90, 20)
Fg("green")
DrawString(45, 285, "Start")
Fg("pale vivid red-yellow")
DrawString(26, 315, "New Game", 47, 345, "Quit", 41, 375, "About")
WAttrib("fg=white", "font=serif,italic,bold,16")
DrawString(12, 150, "Score: " || "0", 12, 170, "Rows: " || "0",
12, 200, "LEVEL: " || "0")
Fg("dark vivid gray")
FillRectangle(119,19,152,451, 119,479,152,17)
WAttrib("fg=pale vivid red-yellow", "bg=dark vivid gray")
DrawRectangle(119,19,151,451, 119,480,151,16)
numrows := score := level := 0
delaytime := 200
colors := table(&window)
every c := ("blue"|"yellow"|"cyan"|"green"|"red"|"white"|
"red-yellow" | "purple-magenta") do
colors[c] := Clone("fg=" || c)
colors["black"] := Clone(&window, "fg=dark vivid gray")
L := list(30)
every !L := list(10, colors["black"])
newobject()
activecells := copy(nextpiece)
activecellcolor := copy(nextcolor)
every point := !activecells do
L[point[1], point[2]] := colors[activecellcolor]
newobject()
end
procedure game_loop()
repeat {
while *Pending() > 0 do {
case Event() of {
Key_Left : move_piece(-1, 0)
Key_Right : move_piece(1, 0)
Key_Down : move_piece(0, 1)
Key_Up : rotate_piece()
" " : drop()
&lpress : {
if 15 <= &x <= 105 then {
if 270 <= &y <= 290 then pause()
else if 300 <= &y <= 320 then return
else if 360 <= &y <= 380 then
about_itetris()
}
}
&lrelease :
if ((15 <= &x <= 105) & (330 <= &y <= 350)) then
exit()
}
}
every point1 := !activecells do {
if point1[1] + 1 = (point2 := !activecells)[1] &
point1[2] = point2[2] then {
}
else if (point1[1] = 30) | (L[point1[1] + 1,
point1[2]] ~=== colors["black"]) then {
if point2[1] = 3 then {
EraseArea(120,481,150,15)
Bg("black")
every cell := !nextpiece do
EraseArea(-40 + (cell[2]-1)*15,
60 + (cell[1]-1)*15, 15, 15)
every (x := 30 to 1 by -1, y := 1 to 10) do {
temp := ?["red-yellow", "yellow", "blue", "cyan",
"red", "green", "purple-magenta"]
Fg(temp)
drawcell(120 + (y-1)*15, 20 + (x-1)*15, temp)
WDelay(1)
}
every (x := 1 to 30, y := 1 to 10) do {
FillRectangle(colors["black"], 120 + (y-1)*15,
20 + (x-1)*15, 15, 15)
WDelay(1)
}
Notice("Game Over")
return
}
while get(Pending())
scanrows()
Fg("black")
DrawString(12, 150, "Score: " || score)
score +:= 5
Fg("white")
DrawString(12, 150, "Score: " || score)
activecells := copy(nextpiece)
activecellcolor := copy(nextcolor)
every point := !activecells do
L[point[1], point[2]] := colors[activecellcolor]
newobject()
EraseArea(120,481,150,15)
Bg("black")
every cell := !activecells do {
EraseArea(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15,
15, 15)
if cell ~=== colors["black"] then
drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
}
every cell := !nextpiece do
drawcell(-40 + (cell[2]-1)*15,
60 + (cell[1]-1)*15, nextcolor)
break
}
}
newactivecells := []
Bg("dark vivid gray")
every cell := !activecells do {
put(newactivecells, copy(cell))
newactivecells[-1, 1] +:= 1
EraseArea(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15,
15, 15)
L[cell[1], cell[2]] := colors["black"]
}
every cell := !newactivecells do {
L[cell[1], cell[2]] := colors[activecellcolor]
drawcell(120 + (cell[2]-1)*15,
20 + (cell[1]-1)*15, activecellcolor)
}
WSync()
activecells := newactivecells
delay(delaytime)
}
end
procedure newobject()
case nextcolor := ?["red-yellow", "red", "yellow", "green",
"cyan", "blue", "purple-magenta"] of {
"red-yellow": {
nextpiece := [ [1,5], [1,6], [2,5], [2,6] ]
}
"red": {
nextpiece := [ [3,6], [1,6], [2,6], [4,6] ]
pieceposition := 1
}
"yellow": {
nextpiece := [ [2,6], [1,6], [2,5], [2,7] ]
}
"green": {
nextpiece := [ [2,6], [1,5], [1,6], [2,7] ]
pieceposition := 1
}
"cyan": {
nextpiece := [ [2,6], [1,6], [1,7], [2,5] ]
pieceposition := 1
}
"blue": {
nextpiece := [ [2,6], [1,5], [2,5], [2,7] ]
}
"purple-magenta": {
nextpiece := [ [2,6], [1,7], [2,5], [2,7] ]
}
}
end
procedure move_piece(x, y)
every point := !activecells do {
# point wants to move to [point[1], point[2] + 1]
if ((point[2] + x) < 1) | ((point[2] + x) > 10) then fail
if point[1] + y > 30 then fail
if L[point[1] + y, point[2] + x] === colors["black"] then
next
every point2 := !activecells do
if (point[1] + y = point2[1]) &
point[2] + x = point2[2] then break next
if L[point[1] + y, point[2] + x] ~=== colors["black"] then
fail
}
newactivecells := []
every cell := !activecells do {
put(newactivecells, copy(cell))
newactivecells[-1, 2] +:= x
newactivecells[-1, 1] +:= y
EraseArea(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15, 15 , 15)
L[cell[1], cell[2]] := colors["black"]
}
EraseArea(120,481,150,15)
every cell := !newactivecells do {
L[cell[1], cell[2]] := colors[activecellcolor]
drawcell(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15,
activecellcolor)
if cell ~=== colors["black"] then
drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
}
WSync()
activecells := newactivecells
end
procedure drop()
repeat {
every point1 := !activecells do {
if point1[1] + 1 = (point2 := !activecells)[1] &
point1[2] = point2[2] then {
}
else if (point1[1] = 30) |
(L[point1[1] + 1, point1[2]] ~===
colors["black"]) then {
while get(Pending())
return
}
}
newactivecells := []
every cell := !activecells do {
put(newactivecells, copy(cell))
newactivecells[-1, 1] +:= 1
EraseArea(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15, 15 , 15)
L[cell[1], cell[2]] := colors["black"]
}
every cell := !newactivecells do {
L[cell[1], cell[2]] := colors[activecellcolor]
drawcell(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15,
activecellcolor)
}
WSync()
activecells := newactivecells
}
end
procedure rotate_piece()
if activecellcolor === "red-yellow" then fail
newactivecells := list()
centerpoint := copy(activecells[1])
differencelist := list()
every point := ! activecells do {
temp := [ centerpoint[1] - point[1],
centerpoint[2] - point[2] ]
put(differencelist, temp)
next
}
every cell := !activecells do
put(newactivecells, copy(cell))
if activecellcolor === ("red" | "green" | "cyan") &
(pieceposition = 2) then {
every foo := 1 to *newactivecells do {
newactivecells[foo,1] := centerpoint[1] + differencelist[foo,2]
newactivecells[foo,2] := centerpoint[2] + differencelist[foo,1] * -1
pieceposition := 1
}
}
else {
every foo := 1 to *newactivecells do {
newactivecells[foo, 1] := centerpoint[1] + differencelist[foo,2] * -1
newactivecells[foo, 2] := centerpoint[2] + differencelist[foo,1]
if activecellcolor === ("red" | "green" | "cyan") &
(pieceposition = 1) then
pieceposition := 2
}
}
every foo := 1 to *newactivecells do {
if not ((1 <= newactivecells[foo, 1] <= 30) &
(1 <= newactivecells[foo, 2] <= 10)) then fail
if L[newactivecells[foo, 1], newactivecells[foo, 2]] ===
colors["black"] then next
every point2 := !activecells do {
if (newactivecells[foo, 1] = point2[1]) &
newactivecells[foo, 2] = point2[2]
then break next
}
if L[newactivecells[foo, 1], newactivecells[foo, 2]] ~===
colors["black"] then fail
}
every cell := !activecells do {
EraseArea(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15, 15 , 15)
L[cell[1], cell[2]] := colors["black"]
}
EraseArea(120,481,150,15)
every cell := !newactivecells do {
L[cell[1], cell[2]] := colors[activecellcolor]
drawcell(120 + (cell[2]-1)*15, 20 + (cell[1]-1)*15,
activecellcolor)
if cell ~=== colors["black"] then
drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
}
WSync()
activecells := newactivecells
end
procedure scanrows()
scanned_rows := table()
rows_to_delete := []
every point := !activecells do {
if \scanned_rows[point[1]] then next
scanned_rows[point[1]] := 1
every (x := 1 to 10) do {
if L[point[1], x] === colors["black"] then {
break next
}
else next
}
put(rows_to_delete, point[1])
}
if *rows_to_delete > 0 then {
Fg("black")
DrawString(12, 150, "Score: " || score, 12, 170, "Rows: " || numrows,
12, 200, "LEVEL: " || level)
numrows +:= *rows_to_delete
level := integer(numrows / 10)
score +:= 50 * (2 ^ (*rows_to_delete - 1))
delaytime := 200 - (10 * level)
Fg("white")
DrawString(12, 150, "Score: " || score, 12, 170, "Rows: " || numrows,
12, 200, "LEVEL: " || level)
deleterows(rows_to_delete)
}
end
procedure deleterows(rows_to_delete)
temp := []
current_row := 30
rows_to_delete := sort(rows_to_delete)
row_set := set()
every insert(row_set, !rows_to_delete)
while current_row >= rows_to_delete[1] do {
push(temp, pull(L))
current_row -:= 1
}
temp_size := *temp
current_row := 1
basesize := *L
while *temp>0 do {
if member(row_set, basesize + current_row) then {
push(L, list(10, colors["black"]))
pop(temp)
}
else
put(L, pop(temp))
current_row +:= 1
}
every (x := 1 to 30, y := 1 to 10) do {
FillRectangle(L[x, y], 120 + (y-1)*15, 20 + (x-1)*15, 15, 15)
if L[x,y] ~=== colors["black"] then
DrawRectangle(colors["white"], 120 + (y-1)*15,
20 + (x-1) * 15, 14, 14)
}
WSync()
end
procedure pause()
text1 := ["Start", "green", 45, 285]
text2 := ["Pause", "red", 40, 285]
button_status := 0
game_status := 0
Bg("black")
EraseArea(16, 271, 89, 19)
Font("sans,bold,16")
Fg("green")
DrawString(45, 285, "Start")
FillRectangle(colors["black"], 120,20,150,450, 120,481,150,15)
every cell := !nextpiece do
EraseArea(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15, 15, 15)
repeat {
Fg("white")
Font("sans,italic,bold,20")
CenterString(195, 234, "-PAUSED-")
if (buttons(15, 105, 270, 290, text1, text2)) == "done" then
break
}
refresh_screen()
game_status := 1
end
procedure buttons(x1, x2, y1, y2, text1, text2)
while *Pending() > 0 do {
case Event() of {
&lpress : {
if (15 <= &x <= 105) & (330 <= &y <= 350) then exit()
if x1 <= &x <= x2 then
if y1 <= &y <= y2 then {
Bg(text1[2])
EraseArea(x1 + 1, y1 + 1, 89, 19)
Font("sans,bold,16")
Fg("black")
DrawString(text1[3], text1[4], text1[1])
button_status := 1
}
else if (360 <= &y <= 380) then about_itetris()
else if (300 <= &y <= 320) then main()
else button_status := 0
}
&ldrag : {
if not ((x1 <= &x <= x2) & (y1 <= &y <= y2)) then
button_status := 0
}
&lrelease: {
if ((x1 <= &x <= x2) & (y1 <= &y <= y2) &
(button_status = 1)) then {
Bg("black")
EraseArea(x1 - 2, y1 - 2, 95, 25)
WAttrib("fg=dark weak greenish cyan", "linewidth=1")
DrawRectangle(x1, y1, 90, 20)
Font("sans,bold,16")
Fg(text2[2])
DrawString(text2[3], text2[4], text2[1])
Font("serif,italic,bold,16")
return "done"
}
return "keep goin"
}
}
px := WAttrib("pointerx")
py := WAttrib("pointery")
if not ((x1 <= &x <= x2) & (y1 <= &y <= y2)) then {
Bg("black")
EraseArea(x1 - 2, y1 - 2, 95, 25)
WAttrib("fg=dark weak greenish cyan", "linewidth=1")
DrawRectangle(x1, y1, 90, 20)
WAttrib("font=sans,bold,16", "fg=" || text1[2])
DrawString(text1[3], text1[4], text1[1])
}
}
end
procedure about_itetris()
about := WOpen("label=About iTetris", "size=300,200", "bg=black",
"fg=white", "posx=10", "posy=155") | fail
every cell := !nextpiece do
EraseArea(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15, 15, 15)
FillRectangle(colors["black"], 120,20,150,450,
120,481,150,15)
CenterString(about, 150, 25, "Written By: David Rice")
CenterString(about, 150, 50, "Communications Arts HS, San Antonio")
CenterString(about, 150, 90, "with technical assistance from")
CenterString(about, 150, 115, "Clinton Jeffery")
CenterString(about, 150, 180, "Christmas 1998")
repeat {
case Event(about) of {
"\e" | "Q" | "q" : break
&lpress : break
}
}
while get(Pending())
WClose(about)
if game_status = 1 then refresh_screen()
end
procedure refresh_screen()
Bg("dark vivid gray")
every cell := !nextpiece do
drawcell(-40 + (cell[2]-1)*15, 60 + (cell[1]-1)*15,
nextcolor)
every cell := !activecells do {
if cell ~=== colors["black"] then
drawcell(120 + (cell[2]-1)*15, 481, activecellcolor)
}
every (x := 1 to 30, y := 1 to 10) do {
FillRectangle(L[x, y], 120 + (y-1)*15, 20 + (x-1)*15, 15, 15)
if L[x,y] ~=== colors["black"] then
DrawRectangle(colors["white"], 120 + (y-1)*15,
20 + (x-1) * 15, 14, 14)
}
end
procedure drawcell(x,y,color)
FillRectangle(colors[color],x,y,15,15)
DrawRectangle(colors["white"], x, y, 14, 14)
end